package node.exp;

import grammar.Lexer;
import grammar.MyError;
import lexical.Key;
import lexical.Word;
import midcode.MidCode;
import midcode.MidcodeGenerator;
import midcode.OPType;
import node.Node;
import symbol.Symbol;
import symbol.SymbolTable;

import java.util.ArrayList;

public class LVal implements Node {
    private final Lexer lexer;
    private final SymbolTable table;
    private final Node father;
    public Symbol symbol;
    public Exp index_1;
    public Exp index_2;
    public ArrayList<Node> nodes = new ArrayList<>();

    public LVal(Lexer lexer, SymbolTable table, Node father) {
        this.lexer = lexer;
        this.table = table;
        this.father = father;
        parseLVal();
    }

    private void parseLVal() {
        Word word = lexer.getWord(0);
        symbol = table.getSymbolByWord(word.word);
        if (symbol == null) {
            lexer.addError(new MyError(word.lineNum, 'c')); //error c
        }
        nodes.add(lexer.getCurWord()); // ident
        if (lexer.isWordType(0, Key.LBRACK)) {
            nodes.add(lexer.getCurWord()); // [
            index_1 = new Exp(lexer, table, this);
            nodes.add(index_1);
            if (lexer.isWordType(0, Key.RBRACK)) {
                nodes.add(lexer.getCurWord()); // ]
            } else {
                lexer.addError(new MyError(lexer.getWord(-1).lineNum, 'k'));
            }
            if (lexer.isWordType(0, Key.LBRACK)) {
                nodes.add(lexer.getCurWord()); // [
                index_2 = new Exp(lexer, table, this);
                nodes.add(index_2);
                if (lexer.isWordType(0, Key.RBRACK)) {
                    nodes.add(lexer.getCurWord()); // ]
                } else {
                    lexer.addError(new MyError(lexer.getWord(-1).lineNum, 'k'));
                }
            }
        }
    }

    public int getValue() {
        if (index_1 == null) {
            return symbol.getVal_0();
        } else if (index_2 == null) {
            return symbol.getVal_1().get(index_1.getValue());
        } else {
            return symbol.getVal_2().get(index_1.getValue()).get(index_2.getValue());
        }
    }

    @Override
    public Node getFather() {
        return father;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Node word : nodes) {
            sb.append(word.toString());
        }
        return sb.append("<LVal>\n").toString();
    }

    @Override
    public String genMidCode() {
        MidcodeGenerator mg = MidcodeGenerator.getInstance();
        if (index_1 == null) {  // dim = 0
            if (symbol.dim == 0) {  // ident是变量，返回ident
                return symbol.getName();
            } else { // ident是数组，返回地址
                String tmp = mg.genTmp();
                mg.addMidcode(new MidCode(OPType.LW_ADDRESS, symbol.getName(), null, tmp));
                return tmp;
            }
        } else if (index_2 == null) {  // dim = 1
            String i = index_1.genMidCode();
            if (symbol.dim == 1) {  // ident是一维数组，取值返回
                String tmp = mg.genTmp();
                mg.addMidcode(new MidCode(OPType.LW_ARRAY, symbol.getName(), i, tmp));
                return tmp;
            } else { // ident是二维数组，返回地址
                String tmp = mg.genTmp();
                mg.addMidcode(new MidCode(OPType.LW_ADDRESS, symbol.getName(), i, tmp));
                return tmp;
            }
        } else {  // dim = 2
            String i = index_1.genMidCode();
            String j = index_2.genMidCode();
            return mg.genArrayIndex(symbol, i, j, null);
        }
    }
}

